﻿using SharpDX;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using 纸片人.CalculateControls;
using 纸片人.InterfaceFolder;
using 纸片人.win2dEffectControl;
using 纸片人.win2dEffectControl.DataClass;
using Vector2 = SharpDX.Vector2;

// The Templated Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234235

namespace 纸片人.CalculateControls
{
    public abstract class OperatorControl : CalculateControl
    {
        protected Panel controlContainer;
 
        protected ExporterDragControl exporterDrag;
        protected ProviderDropControl oneProviderDrop;

        protected ProviderDropControl twoProviderDrop;


   
    
        protected OutputType oneExportType;
        protected string oneExportValueName;
        protected object oneExportValue;

      
        protected ConnectLineUIElement twoConnectElement;
        protected OutputType twoExportType;
        protected string twoExportValueName;
        protected object twoExportValue;



        #region 属性


        #region Header     
        /// <summary>
        /// 获取或设置Header的值
        /// </summary>  
        public Object Header
        {
            get { return (Object)GetValue(HeaderProperty); }
            set { SetValue(HeaderProperty, value); }
        }

        /// <summary>
        /// 标识 Header 依赖属性。
        /// </summary>
        public static readonly DependencyProperty HeaderProperty =
            DependencyProperty.Register("Header", typeof(Object), typeof(OperatorControl), new PropertyMetadata(0, OnHeaderChanged));

        private static void OnHeaderChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            OperatorControl target = obj as OperatorControl;
            Object oldValue = (Object)args.OldValue;
            Object newValue = (Object)args.NewValue;
            if (oldValue != newValue)
                target.OnHeaderChanged(oldValue, newValue);
        }

        protected virtual void OnHeaderChanged(Object oldValue, Object newValue)
        {
        }
        #endregion



        #region OneGenre     
        /// <summary>
        /// 获取或设置OneGenre的值
        /// </summary>  
        public Object OneGenre
        {
            get { return (Object)GetValue(OneGenreProperty); }
            set { SetValue(OneGenreProperty, value); }
        }

        /// <summary>
        /// 标识 OneGenre 依赖属性。
        /// </summary>
        public static readonly DependencyProperty OneGenreProperty =
            DependencyProperty.Register("OneGenre", typeof(Object), typeof(OperatorControl), new PropertyMetadata(0, OnOneGenreChanged));

        private static void OnOneGenreChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            OperatorControl target = obj as OperatorControl;
            Object oldValue = (Object)args.OldValue;
            Object newValue = (Object)args.NewValue;
            if (oldValue != newValue)
                target.OnOneGenreChanged(oldValue, newValue);
        }

        protected virtual void OnOneGenreChanged(Object oldValue, Object newValue)
        {
        }
        #endregion



        #region TwoGenre     
        /// <summary>
        /// 获取或设置TwoGenre的值
        /// </summary>  
        public Object TwoGenre
        {
            get { return (Object)GetValue(TwoGenreProperty); }
            set { SetValue(TwoGenreProperty, value); }
        }

        /// <summary>
        /// 标识 TwoGenre 依赖属性。
        /// </summary>
        public static readonly DependencyProperty TwoGenreProperty =
            DependencyProperty.Register("TwoGenre", typeof(Object), typeof(OperatorControl), new PropertyMetadata(0, OnTwoGenreChanged));

        private static void OnTwoGenreChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            OperatorControl target = obj as OperatorControl;
            Object oldValue = (Object)args.OldValue;
            Object newValue = (Object)args.NewValue;
            if (oldValue != newValue)
                target.OnTwoGenreChanged(oldValue, newValue);
        }

        protected virtual void OnTwoGenreChanged(Object oldValue, Object newValue)
        {
        }
        #endregion


        #region ExporterGenre     
        /// <summary>
        /// 获取或设置ExporterGenre的值
        /// </summary>  
        public Object ExporterGenre
        {
            get { return (Object)GetValue(ExporterGenreProperty); }
            set { SetValue(ExporterGenreProperty, value); }
        }

        /// <summary>
        /// 标识 ExporterGenre 依赖属性。
        /// </summary>
        public static readonly DependencyProperty ExporterGenreProperty =
            DependencyProperty.Register("ExporterGenre", typeof(Object), typeof(OperatorControl), new PropertyMetadata(0, OnExporterGenreChanged));

        private static void OnExporterGenreChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            OperatorControl target = obj as OperatorControl;
            Object oldValue = (Object)args.OldValue;
            Object newValue = (Object)args.NewValue;
            if (oldValue != newValue)
                target.OnExporterGenreChanged(oldValue, newValue);
        }

        protected virtual void OnExporterGenreChanged(Object oldValue, Object newValue)
        {
        }
        #endregion


        public object Value
        {
            get { return (object)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Value.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register("Value", typeof(object), typeof(OperatorControl), new PropertyMetadata(0d));
        #endregion

        public OperatorControl()
        {

            this.DefaultStyleKey = typeof(OperatorControl);

        }

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            GetExportLayer();
            GetTwoProviderLayer();
            GetOneProviderLayer();
        }

    

        #region 第一层
        void GetExportLayer()
        {
            controlContainer = GetTemplateChildFormName<Panel>(nameof(controlContainer));
     
            exporterDrag = GetTemplateChildFormName<ExporterDragControl>(nameof(exporterDrag));
            exporterDrag.CanDrag = true;
            exporterDrag.DragStarting += exporterDrag_DragStarting;

        }



        private void exporterDrag_DragStarting(UIElement sender, DragStartingEventArgs args)
        {
            OnDragExportInvoke();
            OutputData od = new OutputData();
            od.Type = Type;
            od.Exporter = this;
            od.ExportConnectElement =(ExporterDragControl) sender;
            od.ExporterInfo = nameof(Value);
            EffectOutputControl.outputData = od;
        }
        #endregion

        #region 第二层
        void GetOneProviderLayer()
        {


            oneProviderDrop = GetTemplateChildFormName<ProviderDropControl>(nameof(oneProviderDrop));
            oneProviderDrop.DragEnter += TwoProviderDrop_DragEnter;
            oneProviderDrop.Drop += OneProviderDrop_Drop;
            oneProviderDrop.AllowDrop = true;

        }
        private void OneProviderDrop_Drop(object sender, DragEventArgs e)
        {
            OnOneProviderDrop(sender);
        }

        protected abstract void OnOneProviderDrop(object sender);


        #endregion

        #region 第四层
        void GetTwoProviderLayer()
        {


            twoProviderDrop = GetTemplateChildFormName<ProviderDropControl>(nameof(twoProviderDrop));
            twoProviderDrop.Drop += TwoProviderDrop_Drop; ;
            twoProviderDrop.DragEnter += TwoProviderDrop_DragEnter;
            twoProviderDrop.AllowDrop = true;





        }

        private void TwoProviderDrop_DragEnter(object sender, DragEventArgs e)
        {
            OnProviderDragEnter(sender, e);
        }

        private void TwoProviderDrop_Drop(object sender, DragEventArgs e)
        {
            OnTwoProviderDrop(sender);
        }

        protected abstract void OnTwoProviderDrop(object sender);


        #endregion

       protected void SetType(int i)
        {
            twoProviderDrop.Type = oneProviderDrop.Type = $"Int({i})";
            exporterDrag.Type = $"Out({i})";
            switch (i)
            {
                case 1:
                    Type = OutputType.Double;

                    break;
                case 2:
                    Type = OutputType.Vector2;
                    break;
                case 3:
                    Type = OutputType.Vector3;
                    break;
                case 4:
                    Type = OutputType.Vector4;
                    break;
                default:
                    Type = OutputType.Double;
                    break;
            }
        }
        protected abstract void OnProviderDragEnter(object sender, DragEventArgs e);

        public override void Destroy()
        {
            base.Destroy();
           
            oneConnectElement = null;
            oneConnectElement = null;
            twoConnectElement = null;

          ;
        }

        public override void RemoveProvider(ConnectLineUIElement connectElement)
        {
            RemoveExportoneConnectElement(connectElement);
            if (ListExportoneConnectElement.Count > 0)
            {
                (exporterDrag as ExporterDragControl)?.SetDeConnectState();
            }

        }
        public override void RemoveExport(ConnectLineUIElement connectElement)
        {
            if(connectElement == twoConnectElement)
            {
                twoConnectElement = null;
                twoProviderDrop.SetDeConnectState();
            }
            if(connectElement == oneConnectElement)
            {
                oneConnectElement = null;
                oneProviderDrop.SetDeConnectState();
            }

            RemoveProvideroneConnectElement(connectElement);
        }


        protected abstract override void Timer_Tick(object sender, object e);

    }
}
